package auxiliary;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Vector;

import org.joda.time.DateTime;


public class Verifier extends Thread {

	Planner plan;
	DateTime day;
	Database db;
	int currtime;
	boolean valid,dispensacionyproduccioncheck;
	Vector time;
	String timeerror;
	String personalerror;
	String maquinariaerror;
	String faseerror;
	String loteerror;
	String productoerror;
	String[] fasenames;
	
		public Verifier(Planner plan, DateTime day) {
			this.plan = plan;
			this.day = day;
			currtime = 0;
			valid = true;
			dispensacionyproduccioncheck = true;
			
			SimpleDateFormat formatter = new SimpleDateFormat("HH:mm");
			String firsttime = "07:00";
			String endtime = "18:00";
			Calendar cal = Calendar.getInstance();
			Calendar endcal = Calendar.getInstance();

			try {
				cal.setTime(formatter.parse(firsttime));
				endcal.setTime(formatter.parse(endtime));
			} catch (ParseException e1) {
				e1.printStackTrace();
			}

			time = new Vector();

			time.addElement(formatter.format(cal.getTime()));

			while (cal.before(endcal)) {
				cal.add(Calendar.MINUTE, 6);
				time.addElement(formatter.format(cal.getTime()));
			}
			
			fasenames = new String[]{"dispensacion","produccion","llenado","loteado","etiquetado","bandas","empaque"};
			
			timeerror = null;
			personalerror = null;
			maquinariaerror = null;
			faseerror = null;
			loteerror = null;
			productoerror = null;
			
			db = new Database();
		}
		
		
		public synchronized void run() {
			
			//System.out.println("corrio verificar");
		
		HashMap<String,ArrayList<String>> maquinasProduccion = db.retrieveMapMaquinaria(0);
		HashMap<String,ArrayList<String>> maquinasLlenado = db.retrieveMapMaquinaria(1);
		HashMap<String,ArrayList<String>> maquinasLoteado = db.retrieveMapMaquinaria(2);
		
		HashMap<String,ArrayList<String>> allFuncionarios = db.retrieveMapFuncionarios();
		HashMap<String,Planner.Slot> events = new HashMap<String,Planner.Slot>();
		
		for (int i = 0; i < plan.loteids.size() && dispensacionyproduccioncheck; i++) {
			//System.out.println("entro a primer loop");
			int index = plan.loteids.get(i);
			
			int fases[] = plan.lotes.get(index).getFases(day.getDayOfWeek());
			
			for(int j=0; j< fases.length; j++) {
				if(fases[j]!= -1) {
					Planner.Slot currslot = plan.lotes.get(index).getSlot(day.getDayOfWeek(),j+1,0);
					events.put(String.valueOf(index)+":"+plan.lotes.get(index).retrieveFaseStart(j+1, day.getDayOfWeek(), 0,false)+":start", currslot);
					events.put(String.valueOf(index)+":"+plan.lotes.get(index).retrieveFaseEnd(j+1, day.getDayOfWeek(), 0,false)+":end", currslot);
				}
			}
			
			if((fases[0] == -1 && fases[1] == -1) || (fases[0] != -1 && fases[1] != -1))
				dispensacionyproduccioncheck = true;
			else {
				dispensacionyproduccioncheck = false;
				loteerror = String.valueOf(index);
			}
				
			
			
		}
		
		if(dispensacionyproduccioncheck) {
		
			while ((currtime < 110  && day.getDayOfWeek() < plan.planday.plusDays(5).getDayOfWeek()) || (currtime < 50 && day.getDayOfWeek() == plan.planday.plusDays(5).getDayOfWeek())) {
				////System.out.println("entro a loop");
				for (int i = 0; i < plan.loteids.size(); i++) {
					int index = plan.loteids.get(i);
					
					String loteid = String.valueOf(plan.lotes.get(index).loteid);
					
					Planner.Slot currslot = events.get(loteid+":"+currtime+":start");
					
					ArrayList<String> resultmaquina = null;
					ArrayList<String> resultfuncionario = null;
					
					if(currslot!= null) {
						int personalindex = 0;
						
						if(currslot.fase==2) {
							resultmaquina = maquinasProduccion.remove(currslot.maquinariaid);
							for(int j=0; j<currslot.personalid.size();j++) {
								resultfuncionario = allFuncionarios.remove(currslot.personalid.get(j));
								if(resultfuncionario==null) {
									personalindex = j;
									break;
								}
							}
						}
						else if(currslot.fase==3) {
							resultmaquina = maquinasLlenado.remove(currslot.maquinariaid);
							for(int j=0; j<currslot.personalid.size();j++) {
								resultfuncionario = allFuncionarios.remove(currslot.personalid.get(j));
								if(resultfuncionario==null) {
									personalindex = j;
									break;
								}
							}
						}
						else if(currslot.fase==4) {
							resultmaquina = maquinasLoteado.remove(currslot.maquinariaid);
							for(int j=0; j<currslot.personalid.size();j++) {
								resultfuncionario = allFuncionarios.remove(currslot.personalid.get(j));
								if(resultfuncionario==null) {
									personalindex = j;
									break;
								}
							}
						}
						else{
							resultmaquina = new ArrayList<String>();
							for(int j=0; j<currslot.personalid.size();j++) {
								resultfuncionario = allFuncionarios.remove(currslot.personalid.get(j));
								if(resultfuncionario==null) {
									personalindex = j;
									break;
								}
							}
						}
						
						if(resultmaquina==null) {
							loteerror = String.valueOf(index);
							productoerror = plan.lotes.get(index).productname;
							maquinariaerror = currslot.maquinarianame;
							faseerror = fasenames[currslot.fase-1];
							timeerror = (String) time.get(currtime);
							currtime = 110;
							valid = false;
						}
						
						if(resultfuncionario==null) {
							loteerror = String.valueOf(index);
							productoerror = plan.lotes.get(index).productname;
							personalerror = currslot.personalname.get(personalindex);
							faseerror = fasenames[currslot.fase-1];
							timeerror = (String) time.get(currtime);
							currtime = 110;
							valid = false;
						}
					}
					
					
					if(valid) {
						currslot = events.get(loteid+":"+currtime+":end");
						
						if(currslot!= null) {
							if(currslot.fase==2) {
								maquinasProduccion.put(currslot.maquinariaid,new ArrayList<String>());
								for(int j=0; j<currslot.personalid.size();j++) {
									allFuncionarios.put(currslot.personalid.get(j),new ArrayList<String>());
								}
							}
							else if(currslot.fase==3) {
								maquinasLlenado.put(currslot.maquinariaid,new ArrayList<String>());
								for(int j=0; j<currslot.personalid.size();j++) {
									allFuncionarios.put(currslot.personalid.get(j),new ArrayList<String>());
								}
							}
							else if(currslot.fase==4) {
								maquinasLoteado.put(currslot.maquinariaid,new ArrayList<String>());
								for(int j=0; j<currslot.personalid.size();j++) {
									allFuncionarios.put(currslot.personalid.get(j),new ArrayList<String>());
								}
							}
							else{
								for(int j=0; j<currslot.personalid.size();j++) {
									allFuncionarios.put(currslot.personalid.get(j),new ArrayList<String>());
								}
							}
						}
					}
					
					
				}
	
				currtime++;
				//System.out.println("verifier currtime = " + currtime);
				
			}
		}
		else {
			currtime = 110;
		}
		
		//System.out.println("salio segundo loop");
		//System.out.println("verifier currtime = " + currtime);
		
		db.closeConnection();
			
		}
		
		public int getStatus() {
			if(day.getDayOfWeek()==plan.planday.plusDays(5).getDayOfWeek() && currtime >= 50) {
				return 110;
			}
			return currtime;
		}
		
		public boolean getValidity() {
			return valid && dispensacionyproduccioncheck;
		}
		
		public String getErrorString() {
			
			String errorstring = "", maqstring = "", funcstring = "";
			if(dispensacionyproduccioncheck) {
				errorstring = "Error de planeacion en lote " + loteerror + "\nHora: " + timeerror + "\nProducto: " + productoerror + "\nFase: " + faseerror +"\n";
				maqstring = (maquinariaerror!=null)?("Maquinaria: " + maquinariaerror + " no disponible en hora de inicio de fase\n"):"";
				funcstring = (personalerror!=null)?("Funcionario: " + personalerror + " no disponible en hora de inicio de fase\n"):"";
			}
			else {
				errorstring = "Error de planeacion en lote " + loteerror + "\n Dispensacion y Produccion deben existir el mismo dia\n";
			}
			
			return errorstring + maqstring + funcstring;
		}
}
